home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-28 | 33.8 KB | 1,282 lines | [TEXT/MPS ] |
- /*
- File: 2020HalfGateway.cp
-
- Copyright: © 1991-1994 by Apple Computer, Inc.
- All rights reserved.
-
- Part of the AOCE Sample SMSAM Package. Consult the license
- which came with this software for your specific legal rights.
-
- */
-
-
-
- #ifndef __BLJSTANDARDINCLUDES__
- #include "BLJStandardIncludes.h"
- #endif
-
- #ifndef __2020HALFGATEWAY__
- #include "2020HalfGateway.h"
- #endif
-
- #ifndef __OCE__
- #include <OCE.h>
- #endif
-
- #ifndef __OCEMAIL__
- #include <OCEMail.h>
- #endif
-
- #ifndef __OCEMESSAGING__
- #include "OCEMessaging.h"
- #endif
-
- #ifndef __OCESTANDARDDIRECTORY__
- #include <OCEStandardDirectory.h>
- #endif
-
- #ifndef __MAILBUFFER__
- #include "MailBuffer.h"
- #endif
-
- #ifndef __DEBUGGINGGEAR__
- #include "DebuggingGear.h"
- #endif
-
- #ifndef __LETTERLOGWINDOW__
- #include "LetterLogWindow.h"
- #endif
-
- #ifndef __MAILGATEWAY__
- #include "MailGateway.h"
- #endif
-
- #ifndef __UTILITIES__
- #include "Utilities.h"
- #endif
-
- #ifndef __RECIPIENT__
- #include "Recipient.h"
- #endif
-
- #ifndef __STRING__
- #include "String.h"
- #endif
-
- #ifndef __STATUSDATABASE__
- #include "StatusDatabase.h"
- #endif
-
- #ifndef __AYSTHREADGLUE__
- #include "AYSThreadGlue.h"
- #endif
-
- #ifndef __LETTERLOG__
- #include "LetterLog.h"
- #endif
-
- #ifndef __BLJOCEUTILITIES__
- #include "BLJOCEUtilities.h"
- #endif
-
- #ifndef __THREADUTILITIES__
- // #include "ThreadUtilities.h"
- #endif
-
- #ifndef __RESOURCES__
- #include "Resources.h"
- #endif
-
- #ifndef __DATAITEM__
- #include "DataItem.h"
- #endif
-
- /***********************************|****************************************/
-
- #pragma segment T2020HalfGateway
-
- /***********************************|****************************************/
-
- ImplementQueue(T2020Letter,T2020LetterQueue,true);
-
- /***********************************|****************************************/
-
- const short pictID = 1001;
-
- /***********************************|****************************************/
-
- T2020HalfGateway* g2020HalfGateway = nil;
-
- TLetterLogWindow* gAOCELetterLogWindow = nil;
-
- #if debug
- Boolean gReenumerating = false;
- #endif
-
- /***********************************|****************************************/
-
- T2020HalfGateway::T2020HalfGateway ():
- THalfGateway (),
- fWorkingVRefNum ( 0 ),
- fWorkingDirID ( 0 ),
- fShuttingDown ( false ),
- fInRecoveryPhase ( false ),
- fRecoveryPhaseScanThread ( nil ),
- fPeriodicTasksThread ( nil ),
- fRunThreadH ( nil ),
- fScan2020ThreadH ( nil ),
- fPutLettersInto2020ThreadH ( nil ),
- fSendLettersFromOCEToMailGatewayThreadH ( nil ),
- fProcessLetterRecipientReportsThreadH ( nil ),
- fAvailable2020Directories (),
- fReceivedLetters (),
- fLettersFromOCEToBeSent (),
- fReportsFromOCEToBeProcessed (),
- fLettersWaitingForRecipientReports (),
- fDoNotSendLetters ( false ),
- fDoNotReceiveLetters ( false ),
- fNextTimeToUpdateListOfKnownExtendedDirectories ( 0 ),
- fLettersWaitingForRecipientReportsCountdownTimer ( kOneHourInSeconds * 5 )
- {
- #if debug
- g2020HalfGateway = this;
- #endif
-
- ResetStatistics ( );
-
- fAOCEServerHint.aNet = fAOCEServerHint.aNode = fAOCEServerHint.aSocket = 0;
- }
-
- /***********************************|****************************************/
-
- T2020HalfGateway::~T2020HalfGateway ()
- {
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::PutReceivedLettersInto2020()
- {
- do
- {
- TLetter *receivedLetter = fReceivedLetters.Remove();
-
- while ( receivedLetter )
- {
- ReceiveALetter (receivedLetter);
- receivedLetter = fReceivedLetters.Remove();
- }
-
- #if debug
- TSleep( 15 * 60 );
- #else
- TSleep(60*10);
- #endif
-
- }
- while (IsHalfGatewayShuttingDown() == false);
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::ReceiveLetter (TLetter* letter)
- {
- // Update the status item for the number of letters received into 2020
- #if STATUSVARIABLELETTERSFROMMGTOAYSISDEFINED
- IncrementLongStatus(kTotalLettersFromMGtoAYS);
- #endif
-
- // And put this letter into the queue of letters waiting to be processed.
- fReceivedLetters.Append(letter);
-
- return true;
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::SendOCELettersToMailGateway()
- {
- do
- {
- T2020Letter *letter = fLettersFromOCEToBeSent.Remove();
-
- if (letter)
- {
- SendLetter(letter);
- TYield();
- }
- else
- {
- TSleep(60*15);
- }
- }
- while (IsHalfGatewayShuttingDown() == false);
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::ProcessLetterRecipientReports()
- {
- do
- {
- T2020Letter *report = fReportsFromOCEToBeProcessed.Remove();
-
- if (report)
- {
- HandleRecipientReport(report);
- TYield();
- }
- else
- {
- TSleep(60*15);
- }
- }
- while (IsHalfGatewayShuttingDown() == false);
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::Scan2020ForOutgoingLetters ()
- {
- do {
- MSAMEnumeratePB pb;
-
- if ( GetServerQueueID () )
- {
-
- TRY
- {
- memset(&pb, 0, sizeof(pb));
- pb.queueRef = GetServerQueueID();
- pb.startSeqNum = fEnumerateStartSeqNum;
- pb.buffer = AllocateMailBuffer(512);
-
- FAILOSErr(MSAMEnumerateSleep ((MSAMParam*) &pb));
-
- // Now, step through this list, and handle each item.
- short numberOfItems = * (short *) pb.buffer.buffer;
- MSAMEnumerateOutQReply *itemP = (MSAMEnumerateOutQReply *) ((char *) pb.buffer.buffer + sizeof(short));
-
- keithF ( 2, "GWEnumerate: items: " << numberOfItems );
-
- for ( ; numberOfItems > 0; --numberOfItems, ++itemP)
- {
- keithF ( 2, "Item #" << itemP->seqNum << " Resolved? " << (short) itemP->done << " size " << itemP->approxSize );
-
- if (pb.nextSeqNum > 0)
- fEnumerateStartSeqNum = pb.nextSeqNum;
- else
- fEnumerateStartSeqNum = itemP->seqNum+1;
- #if debug
- // If debug flag 5 is on, then delete letters instead of erasing them.
- if (keithFlag.Flag(25))
- {
- MSAMDeletePB pb;
-
- keith << "2020HGwy: DELETING item seq#" << itemP->seqNum << " instead of handling it." << endl;
-
- pb.queueRef = GetServerQueueID();
- pb.seqNum = itemP->seqNum;
- // pb.result = kIPMNoInformation; // shouldn't be necessary, but do it anyway
-
- OSErr err = MSAMDeleteSleep((MSAMParam*) &pb);
-
- if (err)
- keith << "GWDelete: err#=" << err << endl;
-
- itemP->done = true;
- continue;
- }
-
- if (gReenumerating)
- {
- itemP->done = false;
- }
- #endif
- if (itemP->done == false)
- {
- T2020Letter *letter = new T2020Letter(this, GetServerQueueID(), itemP->seqNum);
- Boolean yesItIs;
-
- FAILifFALSE(letter->IsLetterAReport(yesItIs));
- if (yesItIs)
- {
- fReportsFromOCEToBeProcessed.Append(letter);
- }
- else if (fDoNotSendLetters)
- {
- keithDB("T2020HGwy::Scan2020…, letter not sent becaues fDoNotSendLetters == true.");
-
- // Go thru and mark all of the recipients as 'not' received.
- for (RecipientTypeSet recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
- for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount(recipientType); ++recipientIndex) {
- TRecipient* recipient = letter->GetRecipient(recipientType, recipientIndex);
- recipient->SetStatus(cNotReceived);
- }
- }
-
- // And we're done with the letter.
- if ( ! letter->LetterIsCompleted() )
- delete letter;
- }
- else
- {
- fLettersFromOCEToBeSent.Append(letter);
- }
- }
-
- TYield();
- }
- #if debug
- gReenumerating = false;
- #endif
- }
- EXCEPTION
- {
- #if debug
- keith << "GWEnumerate, FAILURE. err=" << EXCEPTIONCODE << endl;
- #endif
- }
- ENDEXCEPTION;
-
- DisposeMailBuffer(pb.buffer);
- }
-
- // Now, sleep for a while...
- TSleep(60*15);
-
- } while (IsHalfGatewayShuttingDown() == false);
- }
-
- /***********************************|****************************************/
-
-
- void DoResendLettersAtStartupWrapper (unsigned long g, unsigned long )
- {
- TSetRefCon('2Scn');
- ( (T2020HalfGateway*) g )->ResendLettersAtStartup ();
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::ResendLettersAtStartup()
- {
- Boolean done = false;
-
- #if debug
- if (keithFlag.Flag ( 25 ) ) {
- keithDB ( "T2020HalfGateway::ResendLettersAtStartup(), skipping recovery since keithFlag(25) is set." );
- done = true;
- }
- #endif
-
- while ((IsHalfGatewayShuttingDown() == false) && (done == false))
- {
- if (GetServerQueueID())
- {
- MSAMEnumeratePB pb;
-
- TRY
- memset(&pb, 0, sizeof(pb));
- pb.queueRef = GetServerQueueID();
- pb.startSeqNum = fEnumerateStartSeqNum;
- pb.buffer = AllocateMailBuffer(512);
-
- FAILOSErr(MSAMEnumerateSleep ((MSAMParam*) &pb));
-
- // Now, step through this list, and handle each item.
- short numberOfItems = * (short *) pb.buffer.buffer;
- MSAMEnumerateOutQReply *itemP = (MSAMEnumerateOutQReply *) ((char *) pb.buffer.buffer + sizeof(short));
-
- keithF ( 2, "GWEnumerate: items: " << numberOfItems );
-
- for ( ; numberOfItems > 0; --numberOfItems, ++itemP)
- {
- keithF ( 2, keith << "Item #" << itemP->seqNum << " Resolved? " << (short) itemP->done << " size " << itemP->approxSize );
-
- if (itemP->done == false)
- {
- T2020Letter *letter = new T2020Letter(this, GetServerQueueID(), itemP->seqNum);
- Boolean yesItIs;
-
- if ((letter->IsLetterAReport(yesItIs)) && (yesItIs == true))
- {
- // Since this is a report, put it into the list of reports to be processed.
- // There will get handled once the server gateway has finished this
- // recovery phase and actually starts running.
- fReportsFromOCEToBeProcessed.Append(letter);
- }
- else
- {
- #if debug
- if (keithFlag.Flag(2))
- {
- TRString subject;
- letter->GetSubject(subject);
- keith << "T2020Hgwy: Resending letter " << subject << " in startup phase." << endl;
- }
- #endif
- ResendLetter(letter);
- }
- } else {
- // All of the recipients for this letter have been 'completed'; so delete the letter.
- MSAMDeletePB deletePB;
-
- deletePB.queueRef = GetServerQueueID();
- deletePB.seqNum = itemP->seqNum;
- deletePB.result = noErr;
-
- keithF ( 1, "2020HalfGwy::Deleting letter " << itemP->seqNum << " from OCE queue." );
-
- OSErr err = MSAMDeleteSleep((MSAMParam*) &deletePB);
- }
-
- fEnumerateStartSeqNum = max(fEnumerateStartSeqNum, itemP->seqNum+1);
- }
-
- // When we've run out of items to enumerate, then we're done, so exit this loop.
- if (pb.nextSeqNum <= 0)
- done = true;
- else
- fEnumerateStartSeqNum = pb.nextSeqNum;
-
- NOHANDLER;
-
- DisposeMailBuffer ( pb.buffer );
- }
-
- // Now, sleep for a while...
- TSleep(60);
- };
-
- fInRecoveryPhase = false;
- fRecoveryPhaseScanThread = nil;
- }
-
- /***********************************|****************************************/
-
- #if debug
- void ReenumerateLast2020Letter()
- {
- if (g2020HalfGateway) {
- g2020HalfGateway->fEnumerateStartSeqNum--;
- gReenumerating = true;
- }
- }
-
- void ReenumerateAll2020Letters()
- {
- if (g2020HalfGateway) {
- g2020HalfGateway->fEnumerateStartSeqNum = 0;
- gReenumerating = true;
- }
- }
- #endif
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::SendLetter (TLetter *letter)
- {
- #define AOCEB6C5SSERVERSENDSMELETTERSISHOULDNOTGET 0
- #if AOCEB6C5SSERVERSENDSMELETTERSISHOULDNOTGET
- TRecipient * recipient = letter->GetRecipient ( fromRecipient, 1 );
-
- if ( recipient && recipient->IsAddressTypePresent() && recipient->GetAddressType() == 'ALNK')
- {
- if ( ! letter->LetterIsCompleted() )
- delete letter;
- return true;
- }
- #endif
-
- fLettersReceivedFromAOCE++;
- return fMailGateway->ReceiveLetter (letter, this);
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::BeginRecoveryPhase()
- {
- #if debug
- if (keithFlag.Flag(2)) {
- keith << "T2020Hgwy: BEGIN RECOVERY PHASE" << endl;
- }
- #endif
-
- fInRecoveryPhase = true;
-
- fRecoveryPhaseScanThread = createThread ('2Rsc', &DoResendLettersAtStartupWrapper, 32000, (unsigned long) this, 0, TNormalMode);
-
- return true;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::IsRecoveryDone()
- {
- return (fInRecoveryPhase == false);
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::FinishRecoveryPhase()
- {
- // Make sure we've finished the recovery phase
- while (IsRecoveryDone() == false)
- TYield();
-
- #if debug
- if (keithFlag.Flag(2)) {
- keith << "T2020Hgwy: FINISH RECOVERY PHASE" << endl;
- }
- #endif
-
- return true;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::ResendLetter (TLetter* letter)
- {
- Boolean result = false;
-
- { CTupleKey key ("2020DoNotSendLetters");
- CDataItem buffer;
-
- if (GetConfigItem(key, buffer))
- fDoNotSendLetters = * (Boolean *) buffer.GetPhysicalStart();
- else
- fDoNotSendLetters = false;
- }
-
- if (fDoNotSendLetters) {
- keithDB("T2020HGwy::Scan2020…, letter not sent becaues fDoNotSendLetters == true.");
-
- // Go thru and mark all of the recipients as 'not' received.
- for (RecipientTypeSet recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
- for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount(recipientType); ++recipientIndex) {
- TRecipient* recipient = letter->GetRecipient(recipientType, recipientIndex);
- recipient->SetStatus(cNotReceived);
- }
- }
-
- // And we're done with the letter.
- if (letter->LetterIsCompleted() == false)
- delete letter;
- } else {
- fLettersReceivedFromAOCE++;
- result = fMailGateway->RereceiveLetter (letter, this);
- }
-
- return result;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::RereceiveLetter (TLetter* letter)
- {
-
- #if debug
- // TEMPORARY!! Go through this letter, and mark all of the recipient's status
- // codes to cReceived. Eventually, when the ack architecture is
- // done, this code goes away, but currently it lets us behave and
- // not infinitely resend mail if we crash frequently.
- if (steveFlag.Flag(9)) {
- // This temporary for Connector
- if (steveFlag.Flag(11)) {
- keith << "2020Hgwy: Setting all recipients’ status == cReceived because steveFlag(9)=true." << endl;
- }
-
- for (unsigned short recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType)
- {
- for (unsigned short index = 1; index <= letter->GetRecipientCount((RecipientTypeSet) recipientType); ++index)
- {
- TRecipient* recipient = letter->GetRecipient((RecipientTypeSet) recipientType, index);
- if (recipient->GetResponsible()) {
- letter->SetRecipientStatus((RecipientTypeSet) recipientType, index, cReceived);
- }
- }
- }
-
- if (letter->LetterIsCompleted() == false) {
- delete letter;
- };
-
- return true;
- }
- #endif
-
- // If the letter has any responsible recipients with a status different from cUnknown,
- // then that letter must already have been sent to Applelink and a report on those
- // recipients received. Thus, we don't have to resend it. However, if none of the recipients
- // have been reported on, then we always resend the letter even though it may have already been
- // sent but we crashed before receiving the first recipient report.
- //
- Boolean letterShouldBeResent = true;
- for (unsigned short recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
- for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount((RecipientTypeSet) recipientType); ++recipientIndex) {
- TRecipient* recipient = letter->GetRecipient((RecipientTypeSet) recipientType, recipientIndex);
-
- if ((recipient) && (recipient->GetResponsible())) {
- RecipientStatusSet recipientStatus;
- if (letter->GetRecipientStatus((RecipientTypeSet) recipientType, recipientIndex, recipientStatus) && (recipientStatus != cUnknown)) {
- letterShouldBeResent = false;
- break;
- }
- }
- }
- }
-
- // Now, either resend the letter or just keep it in the list of letters for acknowledgement purposes.
- if (letterShouldBeResent) {
- // Put this letter where it will be received just like normal.
- fReceivedLetters.Append(letter);
- } else {
- fLettersWaitingForRecipientReports.Append(letter);
- }
-
- return true;
- }
-
- /***********************************|****************************************/
-
- static Boolean ConvertStatusToAOCERecpientStatusCode ( const RecipientStatusSet status, short& aoceRecipientStatus )
- { Boolean result = true;
-
- switch ( status )
- {
- case cReceived:
- aoceRecipientStatus = noErr; break;
-
- case cNoSuchRecipient:
- aoceRecipientStatus = kIPMNoSuchRecipient; break;
-
- case cTimedOut:
- aoceRecipientStatus = kIPMMsgExpired; break;
-
- case cNotResponsible: // should never happen
- aoceRecipientStatus = kIPMNoSuchRecipient; break;
-
- case cAmbiguousRecipient:
- aoceRecipientStatus = kIPMRecipientAmbiguous; break;
-
- case cBadRecipient:
- case cUnknown: // This should never happen
- aoceRecipientStatus = kIPMRecipientMalformed; break;
-
- case cMessageRejectedByDest:
- case cCanNotSupportBCCRecipient:
- case cNotReceived:
- aoceRecipientStatus = kIPMNoTransferMsgRejectedbyDest; break;
-
- case cRecipientCanNotSendToThisAddress:
- aoceRecipientStatus = kIPMRecipientAccessDenied; break;
-
- case cCanNotTranslateContentForRecipient:
- aoceRecipientStatus = kIPMMsgUnreadable; break;
-
- case cGroupExpansionProblem:
- aoceRecipientStatus = kIPMGroupExpansionProblem; break;
-
- case cNoTranslatableContent:
- case cRequireTEXTContent:
- aoceRecipientStatus = kIPMRecipientReqStdCont; break;
-
- case cRequireIMAGContent:
- aoceRecipientStatus = kIPMRecipientReqSnapShot; break;
-
- case cLetterTooLarge:
- aoceRecipientStatus = kIPMNoTransferMsgTooLarge; break;
-
- case cGatewayDiskTemporarilyTooFull:
- aoceRecipientStatus = kIPMNoTransferDiskFull; break;
-
- default:
- aoceRecipientStatus = -1; result = false;
- }
-
-
- return result;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::CreateRecipientReportForLetter(T2020Letter* letter) {
- Boolean result = false;
-
- keithDB( "T2020Hgwy: Creating recipient report for letter" << endl << *letter );
-
- TRY
- // Debugger () ;
-
- // Sanity checking
- FAILNULL(letter);
-
- // Get the stuff we need to fill in the parameter block
- //
- BLJLetterID letterID;
- FAILifFALSE(letter->GetLetterID(letterID));
-
- T2020Recipient* sender = (T2020Recipient*) letter->GetRecipient(fromRecipient, 1);
- FAILNULL(sender);
-
- OCERecipient letterSender;
- FAILifFALSE(sender->GetOCERecipient(letterSender));
-
- // Create the report
- //
- MSAMCreateReportPB createReportPB;
- CLEARBLOCK ( createReportPB );
- createReportPB.queueRef = GetServerQueueID ();
- createReportPB.mailMsgRef = 0;
- createReportPB.msgID = * (MailLetterID*) &letterID;
- createReportPB.sender = &letterSender;
-
- FAILOSErr(MSAMCreateReportSleep((MSAMParam*) &createReportPB));
-
- unsigned long recipientsInReportCount = 0;
-
- TRY
- // Now, cycle through all of the recipients in the letter and report each of
- // their status's we were responsible for.
- for (RecipientTypeSet recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
- for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount(recipientType); ++recipientIndex) {
- T2020Recipient* recipient = (T2020Recipient*) letter->GetRecipient(recipientType, recipientIndex);
-
- if ((recipient) && (recipient->GetResponsible() && ( recipient->GetOriginalRecipientIndex() > 0 ) )) {
- T2020Recipient* recipient = (T2020Recipient*) letter->GetRecipient(recipientType, recipientIndex);
-
- MSAMPutRecipientReportPB putRecipientReportPB;
- CLEARBLOCK ( putRecipientReportPB );
- putRecipientReportPB.mailMsgRef = createReportPB.mailMsgRef;
- putRecipientReportPB.recipientIndex = recipient->GetOriginalRecipientIndex();
-
- keithDB ( "T2020Hgwy: CreateRecReport…, " << *recipient );
-
- TRY
- if ( ConvertStatusToAOCERecpientStatusCode ( recipient->GetStatus(), putRecipientReportPB.result ) )
- {
- FAILOSErr( MSAMPutRecipientReportSleep ( (MSAMParam*) & putRecipientReportPB ) );
- recipientsInReportCount += 1;
- }
-
- EXCEPTION
- keithDB ( "T2020Hgwy::CreateRecipientReportForLetter, not submitting recipient report." );
-
- MSAMSubmitPB abortPB;
-
- CLEARBLOCK ( abortPB );
- abortPB.mailMsgRef = createReportPB.mailMsgRef;
- abortPB.submitFlag = false;
- FAILOSErr( MSAMSubmit( (MSAMParam*) & abortPB ) );
-
- PASSEXCEPTION();
-
- ENDEXCEPTION
- }
- }
- }
-
- if ( recipientsInReportCount <= 0 )
- keithF ( 2, "T2020HGwy::CreateRecReport, created recipient report with letter with no responsible recipients." );
-
- // Now submit the report, cuz we're done
- MSAMSubmitPB submitPB;
- CLEARBLOCK ( submitPB );
- submitPB.mailMsgRef = createReportPB.mailMsgRef;
- submitPB.submitFlag = ( recipientsInReportCount > 0 );
-
- FAILOSErr(MSAMSubmit((MSAMParam*) &submitPB));
-
- EXCEPTION
- result = false;
-
- PASSEXCEPTION();
-
- ENDEXCEPTION
-
- result = true;
-
- EXCEPTION
- result = false;
-
- ENDEXCEPTION
-
- return result;
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::PutPictureIntoLetter (long letterRef, TLetter* receivedLetter)
- {
- Handle picH;
-
- picH = GetResource ('PICT', pictID);
- if ( (receivedLetter->GetSegmentCount( 'SCON' ) > 0) && picH)
- {
- HLock(picH);
-
- MSAMPutContentPB pb;
-
- pb.mailMsgRef = letterRef;
- pb.segmentType = kMailPictSegmentType;
- pb.append = false;
- pb.buffer = AllocateMailBuffer(GetHandleSize(picH), (Ptr) *picH, GetHandleSize(picH));
-
- #if debug
- keith << "2020HGwy: pb.buffer.dataSize = " << pb.buffer.dataSize << "pb.BufferPtr=" << pb.buffer.buffer << endl << flush;
- #endif
-
- pb.buffer.bufferSize = pb.buffer.dataSize;
-
- OSErr err = MSAMPutContentSleep((MSAMParam*) &pb);
-
- #if debug
- if (err || keithFlag.Flag(2))
- keith << "T2020HGwy: MSAMPutContent, err=" << err << endl;
- #endif
-
- // DisposeMailBuffer(pb.buffer);
- ReleaseResource (picH);
- }
- }
-
- /***********************************|****************************************/
-
- BLJTime NowBLJTime ( )
- {
- BLJTime result;
- MachineLocation loc;
-
-
- result.time = GetCurrentGMTSeconds ();
- result.offset = 0;
-
- return result;
- }
-
- /***********************************|****************************************/
-
- int operator < ( const BLJTime& i1, const BLJTime& i2 )
- {
- return ( i1.time + i1.offset < i2.time + i2.offset );
- }
-
- /***********************************|****************************************/
-
- int operator <= ( const BLJTime& i1, const BLJTime& i2 )
- {
- return ( i1.time + i1.offset <= i2.time + i2.offset );
- }
-
- /***********************************|****************************************/
-
- int operator == ( const BLJTime& i1, const BLJTime& i2 )
- {
- return ( i1.time + i1.offset == i2.time + i2.offset );
- }
-
- /***********************************|****************************************/
-
- int operator > ( const BLJTime& i1, const BLJTime& i2 )
- {
- return ( i1.time + i1.offset > i2.time + i2.offset );
- }
-
- /***********************************|****************************************/
-
- int operator >= ( const BLJTime& i1, const BLJTime& i2 )
- {
- return ( i1.time + i1.offset >= i2.time + i2.offset );
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::PeriodicTasks ()
- {
- Boolean done = false;
-
- do {
-
- // Every so often, check through the fLettersWaitingForRecipientReports list
- // and remove any item that has been there more than 7 days.
-
- if ( fLettersWaitingForRecipientReportsCountdownTimer.ExpiredYet () )
- {
- if ( fLettersWaitingForRecipientReportsCountdownTimer.ExpirationCount () > 1 )
- for ( unsigned long i = 1 ; i <= fLettersWaitingForRecipientReports.Count () ; ++ i )
- {
- TLetter* letter = fLettersWaitingForRecipientReports.Get ( i );
-
- if ( letter )
- { BLJTime sendTime;
- if ( letter->GetSendTimeStamp ( sendTime ) && ( sendTime <= NowBLJTime ( ) ) )
- {
- fLettersWaitingForRecipientReports.Remove ( letter );
- TLetter::SetAllUnknownRecipientStatus ( letter, cTimedOut );
- if ( ! letter->LetterIsCompleted () )
- delete letter;
- }
- }
- }
-
- fLettersWaitingForRecipientReportsCountdownTimer.ResetTimer () ;
- }
-
-
- // Fill in some config fields from the config database.
- { CTupleKey key ("2020DoNotSendLetters");
- CDataItem buffer;
-
- if (GetConfigItem(key, buffer))
- fDoNotSendLetters = * (Boolean *) buffer.GetPhysicalStart();
- else
- fDoNotSendLetters = false;
- }
-
- { CTupleKey key ("2020DoNotReceiveLetters");
- CDataItem buffer;
-
- if (GetConfigItem(key, buffer))
- fDoNotReceiveLetters = * (Boolean *) buffer.GetPhysicalStart();
- else
- fDoNotReceiveLetters = false;
- }
-
- TSleep(60*15);
-
- } while ((IsHalfGatewayShuttingDown() == false) && (done == false));
-
- }
-
- /***********************************|****************************************/
-
- //
- // STATUS REPORTING / ERROR REPORTING OPTIONS
- // ==========================================
- //
- Boolean T2020HalfGateway::GetStatusItem(const ATupleKey& key, ADataItem& data)
- { Boolean result = false;
-
- if (key.GetLength() == sizeof(OSType)) {
- OSType keyType = * (OSType *) key.GetData();
-
- switch (keyType) {
- case 'OCPL': // Count-of-Pending-Letters
- data = fReceivedLetters.Count();
- result = true;
- break;
-
- case 'OCAL': // Count-of-Acknowledgement-waiting-Letters
- data = fLettersWaitingForRecipientReports.Count();
- result = true;
- break;
-
- case 'OCLS': // Count-of-Letters-Sent-to-aoce
- data = fLettersSentToAOCE;
- result = true;
- break;
-
- case 'OTCK': // Total-Content-sent-in-K
- data = fTotalKOfContentSentToAOCE;
- result = true;
- break;
-
- case 'OTEK': // Total-Enclosure-sent-in-K
- data = fTotalKOfEnclosuresSentToAOCE;
- result = true;
- break;
-
- case 'NAME': // Gateway name, same as AOCE Forwarder record name
- data = (StringPtr) OCERToPString( ((const RecordID *) fOurForwarderRecord)->local.recordName);
- result = true;
- break;
-
- case 'DESC': // Gateway description
- data = (StringPtr) OCERToPString ( fOurGatewayDescription );
- result = true;
- break;
- }
- };
-
- // If we don't have it yet, try in the status database...
- if (!result) {
- result = THalfGateway::GetStatusItem ( key, data );
- }
-
- return result;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::SetStatusItem(const ATupleKey& key, const ADataItem& buffer)
- {
- Boolean result = THalfGateway::SetStatusItem(key, buffer);
- return result;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::GetStatusStr ( Str255& statusStr ) const
- {
- PLstrcpy ( statusStr, fStatusStr );
- return fStatusStr[0];
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::SetStatusStr ( Str255 statusStr )
- {
- fMailGateway->SetStatusStr ( statusStr );
- if ( PLstrcmp ( fStatusStr, statusStr ) ) {
- keithDB ( "T2020HGwy::SetStatusStr(" << statusStr << ")" );
- }
- PLstrcpy ( fStatusStr, statusStr );
- }
-
- /***********************************|****************************************/
-
- void T2020HalfGateway::ResetStatistics ( )
- {
- fLettersSentToAOCE = 0;
- fLettersReceivedFromAOCE = 0;
- fTotalKOfContentSentToAOCE = 0;
- fTotalKOfEnclosuresSentToAOCE = 0;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::HandleMonitoringEvent ( const ADataItem& event )
- { Boolean result = false;
-
- if ( event.GetPhysicalLength () == sizeof(OSType) )
- {
- OSType monitoringEvent = * ( OSType * ) event.GetPhysicalStart();
-
- switch ( monitoringEvent )
- {
- case 'RSET': // 'Reset' statistics.
- fLettersSentToAOCE =
- fLettersReceivedFromAOCE =
- fTotalKOfContentSentToAOCE =
- fTotalKOfEnclosuresSentToAOCE = 0;
- result = false; // we didn't 'completely' handle this event.
- break;
- }
- }
-
- return result;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020HalfGateway::HandleRecipientReport (T2020Letter* report)
- {
- Boolean result = false;
-
- TRY
- // Get the gateway information block from the letter. This block will contain the letterID
- // of the letter this report is for, and we use this ID to determine which letter in the
- // fLettersWaitingForRecipientReports. list we report for.
- OCECreatorType blockType;
- blockType.msgCreator = fOurGatewayMailExtensionType;
- blockType.msgType = kMailMSAMType;
- MyGWYIBlockRecord messageInfo;
- unsigned long actualReturnedDataSize;
-
- FAILifFALSE(report->GetLetterBlockData(blockType, 1, (void*) &messageInfo, sizeof(messageInfo), 0, actualReturnedDataSize));
-
- keithF(2, "T2020Half::Got 'gwyi' block with this data:" << endl; DumpHex ( keith, & messageInfo, sizeof ( messageInfo ) ) );
-
- // Now, find the letter in fLettersWaitingForRecipientReports. with the right letterID.
- TLetter* letter = nil;
-
- for (int index = 1; index <= fLettersWaitingForRecipientReports.Count(); ++index)
- {
- TLetter* tempLetter = fLettersWaitingForRecipientReports.Get(index);
-
- BLJLetterID letterID;
- if (tempLetter && tempLetter->GetLetterID(letterID))
- {
- if ( letterID == messageInfo.letterID )
- {
- keithF(2, "T2020Hgwy: HandleRecipientReport, found letter " << letterID << " for report in fLettersWaitingForRecipientReports." );
-
- letter = tempLetter;
- break;
- }
- }
- }
-
- if (letter == nil)
- {
- keith << "T2020Hgwy: HandleRecipientReport, no letter for report " << messageInfo.letterID << endl;
- if ( keithFlag.Flag(2)) {
- keith << "These are the letters in the list waiting for reports:" << endl;
- for (int index = 1; index <= fLettersWaitingForRecipientReports.Count(); ++index)
- {
- TLetter* tempLetter = fLettersWaitingForRecipientReports.Get(index);
-
- BLJLetterID letterID;
- if (tempLetter && tempLetter->GetLetterID(letterID))
- {
- keith << index << ") " << letterID << " ";
- }
- }
-
- keith << endl;
- }
- letter = nil;
- }
- else
- {
- // Enumerate across all of the recipients in this report
- for (unsigned long index = 1; index <= report->GetRecipientReportStatusCount(); ++index)
- {
- unsigned short recipientIndex;
- OSErr recipientResult;
-
- if (report->GetRecipientReportStatus (index, recipientIndex, recipientResult)) {
- // Find the recipientIndex-th recipient in the letter, and set it's
- // status to the appropriate value.
- keithF(2, "HandleRecipientReport: #" << index << " recipient#" << recipientIndex << " status=" << recipientResult );
- }
- }
-
- // Lastly, mark all of the responsible recipients as 'done', so that this letter will
- // 'go away' when it is finished.
- for (unsigned short recipientType = fromRecipient; recipientType <= bccRecipient; recipientType++)
- {
- for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount((RecipientTypeSet) recipientType); ++recipientIndex)
- { TRecipient* recipient = letter->GetRecipient((RecipientTypeSet) recipientType, recipientIndex);
-
- if ( recipient && recipient->GetResponsible())
- letter->SetRecipientStatus((RecipientTypeSet) recipientType, recipientIndex, cReceived);
- }
- }
-
- if (letter->GetUnknownRecipientCount() == 0)
- {
- keithF(2, "T2020Hgwy: HandleRecipientReport, all recipients of " << messageInfo.letterID << " are handled, deleting." );
-
- // Now, we're done with the letter, so remove it from out list of letters
- // waiting for reports and then let the letter know that we're done with it.
- fLettersWaitingForRecipientReports.Remove(letter);
-
- if (!letter->LetterIsCompleted()) {
- delete letter;
- }
- }
- else
- {
- keithF(2, "T2020Hgwy: HandleRecipientReport, for letter " << messageInfo.letterID << ", " << letter->GetUnknownRecipientCount() << " recipients are unreported." );
- }
- }
-
- result = true;
-
- EXCEPTION
- result = false;
-
- ENDEXCEPTION
-
- delete report;
-
- return result;
- }
-
- /***********************************|****************************************
- *
- *
- * AOCE High Level Event Handlers
- * ==============================
- *
- *
- ***********************************|****************************************/
-
- Boolean T2020HalfGateway::HandleAppleMailHighLevelEvent ( const EventRecord& event )
- { Boolean result = false;
-
- if ( ( event.what == kHighLevelEvent ) &&
- ( event.message == kMailAppleMailCreator ) )
- {
- switch ( * (long *) & event.where )
- {
- case kMailEPPCMsgPending:
- AppleEventMsgPendingEvent ();
- result = true;
- break;
-
- case kMailEPPCAdmin:
- AppleEventAdminEvent ( );
- result = true;
- break;
-
- default:
- break;
- }
- }
-
- return result;
- }
-
- /***********************************|****************************************/
-
- OSErr T2020HalfGateway::AppleEventMsgPendingEvent ( void )
- {
- // Wake up the thread that will check our AOCE queue
- if ( fScan2020ThreadH )
- fScan2020ThreadH->Wake();
-
- return noErr;
- }
-
- /***********************************|****************************************/
-
- OSErr T2020HalfGateway::AppleEventAdminEvent ( void )
- {
- // Get the shared-memory-common-area for this event
- SMCA * smca;
-
- TargetID sender;
- unsigned long refCon;
- unsigned long dataLength = sizeof(smca);
-
- OSErr result = AcceptHighLevelEvent ( & sender, & refCon, (Ptr) & smca, & dataLength );
- if ( result == noErr )
- {
-
- if ( smca )
- { void * voidParams = (void*) & smca->u;
-
- switch ( smca->userBytes )
- {
- // Our connectivity has changed
- case kSMSAMNotifyFwdrSetupChange:
- break;
-
- // The name of our SMSAM has changed
- case kSMSAMNotifyFwdrNameChange:
- break;
-
- // The password for our SMSAM has been changed
- case kSMSAMNotifyFwdrPwdChange:
- break;
-
- case kSMSAMGetDynamicFwdrParams:
- SMSAMDynamicParams * dynamicParams = (SMSAMDynamicParams*) voidParams;
-
- dynamicParams->curDiskUsed = 7;
- dynamicParams->curMemoryUsed = 8;
- break;
- }
- }
-
- smca->result = noErr;
- }
-
- return result;
- }
-
- /***********************************|****************************************/
-